package com.tdam2011.grupo02.ui;

import java.util.ArrayList;
import java.util.HashMap;

import com.tdam2011.grupo02.widget.popup.ActionItem;
import com.tdam2011.grupo02.widget.popup.QuickAction;

import com.tdam2011.grupo02.R;
import com.tdam2011.grupo02.compatibility.ActionBarListActivity;
import com.tdam2011.grupo02.domain.ContactosInfo;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.SearchManager;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnDismissListener;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

public class ContactosListActivity extends ActionBarListActivity {

	Cursor cursor;
	String buscar;
	String parametro;
	private Cursor tipos;
	private ContactosInfoAdapter adapter;
	private static final int ID_LLAMADA = 1;
	private static final int ID_SMS = 2;
	private static final int ID_MAIL = 3;
	private static final int ID_HISTORIAL = 4;
	private static final int ID_MSGWEB = 5;
	private static final int ID_MOBILE_CONNECTION = 6;
	private static final int ID_NO_CONNECTION = 7;
	private QuickAction mQuickAction;
	private GestureDetector gestureDetector;
	View.OnTouchListener gestureListener;
	private int posicion;
	private String notificacion;
	private String consulta;
	private HashMap<String, Uri> imgUri;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.contacto);

		setTitle(R.string.txtvMainContactos);

		Intent intent = getIntent();
		if (Intent.ACTION_VIEW.equals(intent.getAction())) {
			Intent contacto = new Intent(this,
					ContactoSeleccionListActivity.class);
			Uri uri = intent.getData();
			Cursor cursor = managedQuery(uri,
					new String[] { ContactsContract.Contacts._ID }, null, null,
					null);

			if (cursor.moveToFirst()) {
				String aux = cursor.getString(0);
				contacto.putExtra("contactoId", aux);
				startActivity(contacto);
			}
			finish();
		} else {
			if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
				consulta = intent.getStringExtra(SearchManager.QUERY);
			}

			createActionItems();
			setActionItemClickListener();

			getTiposContactos();

			gestureDetector = new GestureDetector(new ContactsGestureDetector());
			gestureListener = new View.OnTouchListener() {
				public boolean onTouch(View v, MotionEvent event) {
					return gestureDetector.onTouchEvent(event);
				}
			};
			getListView().setOnTouchListener(gestureListener);
			registerForContextMenu(getListView());

		}
	}

	private void createActionItems() {
		ActionItem llamadasItem = new ActionItem(ID_LLAMADA, null,
				getResources().getDrawable(android.R.drawable.sym_action_call));
		ActionItem smsItem = new ActionItem(ID_SMS, null, getResources()
				.getDrawable(android.R.drawable.sym_action_chat));
		ActionItem mailItem = new ActionItem(ID_MAIL, null, getResources()
				.getDrawable(R.drawable.quick_action_mail));
		ActionItem historialItem = new ActionItem(ID_HISTORIAL, null,
				getResources().getDrawable(R.drawable.quick_action_log));
		ActionItem msgWebItem = new ActionItem(ID_MSGWEB, null, getResources()
				.getDrawable(R.drawable.quick_action_msgweb));

		mQuickAction = new QuickAction(this);

		mQuickAction.addActionItem(llamadasItem);
		mQuickAction.addActionItem(smsItem);
		mQuickAction.addActionItem(mailItem);
		mQuickAction.addActionItem(historialItem);
		mQuickAction.addActionItem(msgWebItem);
	}

	private void setActionItemClickListener() {
		mQuickAction
				.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener() {
					@Override
					public void onItemClick(QuickAction quickAction, int pos,
							int actionId) {

						switch (actionId) {
						case ID_LLAMADA:
							showDialog(ID_LLAMADA);
							break;
						case ID_SMS:
							showDialog(ID_SMS);
							break;
						case ID_MAIL:
							showDialog(ID_MAIL);
							break;
						case ID_HISTORIAL:
							viewLog();
							break;
						case ID_MSGWEB:
							sendMsgWeb();
							break;
						}
					}
				});
	}

	private void getTiposContactos() {
		String[] projectionTipos = new String[] {
				ContactsContract.RawContacts._ID,
				ContactsContract.RawContacts.CONTACT_ID,
				ContactsContract.RawContacts.ACCOUNT_NAME };
		tipos = getContentResolver().query(
				ContactsContract.RawContacts.CONTENT_URI,
				projectionTipos,
				ContactsContract.RawContacts.CONTACT_ID + " IS NOT NULL AND "
						+ ContactsContract.RawContacts.ACCOUNT_NAME
						+ " IS NOT NULL", null, null);
	}

	class ContactsGestureDetector extends
			com.tdam2011.grupo02.support.MyGestureDetector {

		public ContactsGestureDetector() {
			super(getListView());
			// TODO Auto-generated constructor stub
		}

		@Override
		public void myOnItemClick(int position) {
			cursor.moveToPosition(position);
			String aux = cursor.getString(cursor
					.getColumnIndex(ContactsContract.Contacts._ID));
			Intent intent = new Intent(ContactosListActivity.this,
					ContactoSeleccionListActivity.class);
			intent.putExtra("contactoId", aux);
			startActivity(intent);

		}

		@Override
		public void onRTLFling(int pos) {

		}

		@Override
		public void onLTRFling(int pos) {
			posicion = pos;
			int firstPosition = getListView().getFirstVisiblePosition()
					- getListView().getHeaderViewsCount();
			int wantedChild = posicion - firstPosition;

			if (wantedChild < 0 || wantedChild >= getListView().getChildCount()) {
				return;
			}
			View wantedView = getListView().getChildAt(wantedChild);

			mQuickAction.show(wantedView);
		}

	}

	/**
	 * Obtiene la lista de contactos del celular.
	 * 
	 * @return cursor para acceder a la lista de contactos.
	 */
	private Cursor getContacts() {

		SharedPreferences myPreference = PreferenceManager
				.getDefaultSharedPreferences(this);

		boolean filtrarTel = myPreference.getBoolean(
				getString(R.string.preferenceContactosFTel), false);
		boolean filtrarMail = myPreference.getBoolean(
				getString(R.string.preferenceContactosFM), false);
		String filtrarTipo = myPreference.getString(
				getString(R.string.preferenceContactosFTipo), "0");
		String ordenarForma = myPreference.getString(
				getString(R.string.preferenceContactosOForma), "0");

		Uri uri = ContactsContract.Contacts.CONTENT_URI;
		String[] projection = new String[] { ContactsContract.Contacts._ID,
				ContactsContract.Contacts.DISPLAY_NAME };
		StringBuilder selection = new StringBuilder();
		String[] selectionArgs = null;
		String forma = "ASC";

		String AND = "";
		int selectionSize = selection.length();

		if (!ordenarForma.equals("0"))
			forma = "DESC";
		String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
				+ " COLLATE LOCALIZED " + forma;

		if (consulta != null) {
			selection
					.append(ContactsContract.Contacts.DISPLAY_NAME + " LIKE ?");
			selectionArgs = new String[] { "%" + consulta + "%" };
		}
		if (filtrarTel) {
			selection.append(AND + ContactsContract.Contacts.HAS_PHONE_NUMBER
					+ " = 1");
			AND = " AND ";
		}
		if (filtrarMail)
			filtrarMail(selection, AND, selectionSize);

		if (!filtrarTipo.equals("0")) {
			if (filtrarTipo.equals("1"))
				filtrarTipoTelefono(selection, AND, selectionSize);
			else
				filtrarTipoCuenta(selection, AND, selectionSize, filtrarTipo);
		}

		cursor = null;
		cursor = getContentResolver().query(uri, projection,
				selection.toString(), selectionArgs, sortOrder);
		startManagingCursor(cursor);

		consulta = null;
		return cursor;
	}

	private void filtrarMail(StringBuilder selection, String AND,
			int selectionSize) {
		Cursor emailCur = getContentResolver().query(
				ContactsContract.CommonDataKinds.Email.CONTENT_URI,
				new String[] { ContactsContract.CommonDataKinds.Email._ID,
						ContactsContract.CommonDataKinds.Email.CONTACT_ID },
				null, null, null);

		ArrayList<String> id = new ArrayList<String>();
		emailCur.moveToFirst();
		String contactId;
		while (emailCur.moveToNext()) {
			contactId = emailCur
					.getString(emailCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Email.CONTACT_ID));
			if (contactId != null)
				id.add(contactId);
		}

		selection.append(AND + ContactsContract.Contacts._ID + " IN (");
		for (String contactIdItem : id) {
			selection.append(contactIdItem + ",");
		}
		selectionSize = selection.length();
		selection.replace(selectionSize - 1, selectionSize, ")");
		AND = " AND ";
	}

	private void filtrarTipoTelefono(StringBuilder selection, String AND,
			int selectionSize) {
		if (tipos.moveToFirst()) {
			selection.append(AND + ContactsContract.Contacts._ID + " NOT IN (");
			do {
				selection
						.append(tipos.getString(tipos
								.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID))
								+ ",");
			} while (tipos.moveToNext());
			selectionSize = selection.length();
			selection.replace(selectionSize - 1, selectionSize, ")");
			AND = " AND ";
		}
	}

	private void filtrarTipoCuenta(StringBuilder selection, String AND,
			int selectionSize, String filtrarTipo) {
		if (tipos.moveToFirst()) {
			selection.append(AND + ContactsContract.Contacts._ID + " IN (");
			do {
				if (filtrarTipo
						.equals(tipos.getString(tipos
								.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_NAME))))
					selection
							.append(tipos.getString(tipos
									.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID))
									+ ",");
			} while (tipos.moveToNext());
			selectionSize = selection.length();
			selection.replace(selectionSize - 1, selectionSize, ")");
			AND = " AND ";
		}
	}

	/**
	 * Construye la lista de contactos basandose en los filtros
	 */
	private void populateContactList() {
		// Construye adapter con entradas de contactos

		adapter = new ContactosInfoAdapter(ContactosListActivity.this);
		setListAdapter(adapter);

		ContactosInfo info = new ContactosInfo();
		String idColumn = ContactsContract.Contacts._ID;
		String displayName = ContactsContract.Contacts.DISPLAY_NAME;
		String contactId = ContactsContract.RawContacts.CONTACT_ID;
		String accountName = ContactsContract.RawContacts.ACCOUNT_NAME;
		String id;

		getImg();

		while (cursor.moveToNext()) {
			id = cursor.getString(cursor.getColumnIndex(idColumn));
			info.setImagen(imgUri.get(id));

			info.setNombre(cursor.getString(cursor.getColumnIndex(displayName)));

			if (tipos.moveToFirst()) {
				do {
					if (id.equals(tipos.getString(tipos
							.getColumnIndex(contactId)))) {
						info.setTipo(tipos.getString(tipos
								.getColumnIndex(accountName)));
						break;
					}
				} while (tipos.moveToNext());
			}
			if (info.getTipo() == null)
				info.setTipo(getString(R.string.opcionContactosFTipoTel));

			adapter.addContactosInfo(info);
			info = new ContactosInfo();
		}
		adapter.notifyDataSetChanged();

		this.getListView().setTextFilterEnabled(true);
		setCantidadContactos(cursor.getCount());

	}

	private void getImg() {
		imgUri = new HashMap<String, Uri>();
		Cursor cur = getContentResolver()
				.query(ContactsContract.Data.CONTENT_URI,
						new String[] { ContactsContract.Data._ID,
								ContactsContract.Data.CONTACT_ID },
						ContactsContract.Data.MIMETYPE
								+ "='"
								+ ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE
								+ "'", null, null);
		if(cur.moveToFirst()){
			do {
				imgUri.put(
						cur.getString(cur
								.getColumnIndex(ContactsContract.Data.CONTACT_ID)),
						Uri.withAppendedPath(
								ContentUris
										.withAppendedId(
												ContactsContract.Contacts.CONTENT_URI,
												Long.parseLong(cur.getString(cur
														.getColumnIndex(ContactsContract.Data.CONTACT_ID)))),
								ContactsContract.Contacts.Photo.CONTENT_DIRECTORY));
			} while (cur.moveToNext());
		}
	}

	private void setCantidadContactos(int cant) {
		TextView text = (TextView) findViewById(R.id.txtvCantidadContactos);
		text.setText(" " + cant);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater menuInflater = getMenuInflater();
		menuInflater.inflate(R.menu.options_menu_contactos, menu);

		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			finish();
			break;
		case R.id.menu_search:
			onSearchRequested();
			break;
		case R.id.menu_settings:
			Intent intent = new Intent(ContactosListActivity.this,
					ContactosPreferenceActivity.class);
			startActivity(intent);
			break;
		}

		return super.onOptionsItemSelected(item);
	}

	private void viewLog() {
		Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
		String selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
		final Cursor pCur = getContactDataShowDialog(uri, selection);

		String id = cursor.getString(cursor
				.getColumnIndex(ContactsContract.Contacts._ID));
		String nombre = cursor.getString(cursor
				.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

		if (pCur.moveToFirst()) {
			String numero = pCur
					.getString(pCur
							.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
			ContactActionControllerSingleton
					.getInstance(ContactosListActivity.this)
					.getContactActionController().viewLog(nombre, numero, id);
		}
	}

	private void sendMsgWeb() {
		if (verificarConexionInternet()) {
			ContactActionControllerSingleton
					.getInstance(ContactosListActivity.this)
					.getContactActionController().sendMsgWeb();
		} else if (notificacion.equals(getString(R.string.msgInternetMobileConnection)))
			showDialog(ID_MOBILE_CONNECTION);
		else
			showDialog(ID_NO_CONNECTION);
	}

	private boolean verificarConexionInternet() {
		ConnectivityManager connectivity;
		NetworkInfo wifiInfo, mobileInfo;

		connectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		wifiInfo = connectivity.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
		mobileInfo = connectivity
				.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);

		if (wifiInfo.isConnected()) {
			return true;
		} else if (mobileInfo.isConnected()) {
			notificacion = getString(R.string.msgInternetMobileConnection);
			return false;
		} else {
			notificacion = getString(R.string.msgNoInternetConnectionWebService);
			return false;
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		Dialog dialog = null;
		if (id == ID_LLAMADA || id == ID_SMS) {
			dialog = createPhoneDialog(id);
		} else if (id == ID_MAIL) {
			dialog = createMailDialog();
		} else if (id == ID_MOBILE_CONNECTION) {
			dialog = createMobileConnectionDialog();
		} else if (id == ID_NO_CONNECTION) {
			dialog = createNoConnectionDialog();
		} else {
			dialog = super.onCreateDialog(id);
		}
		return dialog;
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		super.onPrepareDialog(id, dialog);
	}

	private Dialog createMailDialog() {
		Uri uri = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
		String selection = ContactsContract.CommonDataKinds.Email.CONTACT_ID;
		final Cursor pCur = getContactDataShowDialog(uri, selection);
		final String nombre = cursor.getString(cursor
				.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

		String[] selectionCursor = new String[] {
				ContactsContract.CommonDataKinds.Email.TYPE,
				ContactsContract.CommonDataKinds.Email.DATA1 };
		String type = ContactsContract.CommonDataKinds.Email.TYPE;
		String label = ContactsContract.CommonDataKinds.Email.LABEL;
		int typeCustom = Email.TYPE_CUSTOM;

		SimpleCursorAdapter a = getContactDataCursorAdapter(pCur,
				selectionCursor, type, label, typeCustom);

		OnDismissListener onDimiss = new OnDismissListener() {

			@Override
			public void onDismiss(DialogInterface dialog) {
				removeDialog(ID_MAIL);
			}
		};

		if(!a.isEmpty()){
			AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle(
					nombre).setAdapter(a,
					new android.content.DialogInterface.OnClickListener() {
						public void onClick(final DialogInterface dialog,
								final int item) {
							pCur.moveToPosition(item);
							String mail = pCur.getString(pCur
									.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA1));
							ContactActionControllerSingleton
									.getInstance(ContactosListActivity.this)
									.getContactActionController()
									.sendMail(nombre, mail);
						}
					});
			AlertDialog dialog = builder.create();
			dialog.setOnDismissListener(onDimiss);
			return dialog;
		}
		return null;
	}

	private Dialog createPhoneDialog(final int id) {
		Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
		String selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
		final Cursor pCur = getContactDataShowDialog(uri, selection);
		String nombre = cursor.getString(cursor
				.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

		String[] selectionCursor = new String[] {
				ContactsContract.CommonDataKinds.Phone.TYPE,
				ContactsContract.CommonDataKinds.Phone.NUMBER };
		String type = ContactsContract.CommonDataKinds.Phone.TYPE;
		String label = ContactsContract.CommonDataKinds.Phone.LABEL;
		int typeCustom = Phone.TYPE_CUSTOM;

		SimpleCursorAdapter a = getContactDataCursorAdapter(pCur,
				selectionCursor, type, label, typeCustom);

		OnDismissListener onDimiss = new OnDismissListener() {

			@Override
			public void onDismiss(DialogInterface dialog) {
				removeDialog(id);
			}
		};

		if(!a.isEmpty()){
			AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle(
					nombre).setAdapter(a,
					new android.content.DialogInterface.OnClickListener() {
						public void onClick(final DialogInterface dialog,
								final int item) {
							pCur.moveToPosition(item);
							String numero = pCur.getString(pCur
									.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
							if (id == ID_LLAMADA)
								ContactActionControllerSingleton
										.getInstance(ContactosListActivity.this)
										.getContactActionController()
										.makeCall(numero);
							else
								ContactActionControllerSingleton
										.getInstance(ContactosListActivity.this)
										.getContactActionController()
										.sendSMS(numero);
						}
					});
			AlertDialog dialog = builder.create();
			dialog.setOnDismissListener(onDimiss);
			return dialog;
		}
		return null;
	}

	private Cursor getContactDataShowDialog(Uri uri, String selection) {
		cursor.moveToPosition(posicion);
		String id = cursor.getString(cursor
				.getColumnIndex(ContactsContract.Contacts._ID));

		Cursor pCur = getContentResolver().query(uri, null, selection + " = ?",
				new String[] { id }, null);
		return pCur;
	}

	private SimpleCursorAdapter getContactDataCursorAdapter(Cursor pCur,
			String[] selection, final String typeColumn,
			final String labelColumn, final int typeCustom) {

		SimpleCursorAdapter a = new SimpleCursorAdapter(
				ContactosListActivity.this,
				R.layout.item_contact_options_dialog, pCur, selection,
				new int[] { R.id.txtTipos, R.id.txtNumeros });

		a.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
			public boolean setViewValue(View view, Cursor cursor,
					int columnIndex) {
				// Let the adapter handle the binding if the column is not TYPE
				if (columnIndex != cursor.getColumnIndex(typeColumn)) {
					return false;
				}
				int type = cursor.getInt(cursor.getColumnIndex(typeColumn));
				String label = null;
				// Custom type? Then get the custom label
				if (type == typeCustom) {
					label = cursor.getString(cursor.getColumnIndex(labelColumn));
				}
				// Get the readable string
				String text = (String) Phone.getTypeLabel(getResources(), type,
						label);
				// Set text
				((TextView) view).setText(text.trim());
				return true;
			}
		});
		return a;
	}

	private Dialog createMobileConnectionDialog() {
		OnClickListener clickOk = new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				ContactActionControllerSingleton
						.getInstance(ContactosListActivity.this)
						.getContactActionController().sendMsgWeb();
			}
		};

		Dialog dialog = new AlertDialog.Builder(this)
				.setIcon(R.drawable.quick_action_msgweb)
				.setTitle(getString(R.string.connectionDialogTitle))
				.setPositiveButton(getString(R.string.alertBtnOk),
						clickOk)
				.setNegativeButton(getString(R.string.alertBtnCancel),
						null).setMessage(notificacion).create();
		return dialog;
	}

	private Dialog createNoConnectionDialog() {
		Dialog dialog = new AlertDialog.Builder(this)
				.setIcon(R.drawable.quick_action_msgweb)
				.setTitle(getString(R.string.connectionDialogTitle))
				.setPositiveButton(getString(R.string.alertBtnOk),
						null).setMessage(notificacion).create();
		return dialog;
	}

	@Override
	protected void onResume() {
		super.onResume();
		if (Intent.ACTION_SEARCH.equals(getIntent().getAction()))
			consulta = getIntent().getStringExtra(SearchManager.QUERY);
		this.setListAdapter(null);
		GetContactsTask task = new GetContactsTask();
		task.execute(this);
	}

	protected class GetContactsTask extends AsyncTask<Context, Integer, String> {

		@Override
		protected String doInBackground(Context... params) {
			getContacts();
			return null;
		}

		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);
			populateContactList();
		}
	}
}
